package cn.hd01.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.WebUtils;

import cn.hd01.repository.UploadRepository;
import cn.hd01.repository.entity.Upload;
import cn.hd01.service.UploadService;
import cn.hd01.web.util.WebException;

import com.google.common.collect.Lists;

/**
 * @author cyb
 * @date 2017/5/10.
 */
@Service
public class UploadServiceImpl extends BaseServiceImpl<Upload, Integer> implements UploadService {
	private Logger logger = LoggerFactory.getLogger(UploadServiceImpl.class);
	
    // 上传基础路径
    private final String basePath;

    private UploadRepository repository;

    @Autowired
    public UploadServiceImpl(UploadRepository repository, ServletContext servletContext) throws Exception {
        super(repository);
        this.repository = repository;

        basePath = WebUtils.getRealPath(servletContext, "/upload/");
    }

    @Override
    public List<Upload> saveUploadAndFile(MultipartFile[] files, String type, Integer refId) {
        List<Upload> uploadList = Lists.newArrayListWithCapacity(files.length);
        Upload upload;
        for (MultipartFile file : files) {
            upload = new Upload(type, refId, file.getOriginalFilename());
            upload.setUrl(buildUrl(upload));

            uploadList.add(upload);
        }
        List<Upload> result = this.save(uploadList);

        try {
            String path = buildPath(type, refId);
            File folder = new File(path);
            if (!folder.exists()) {
                folder.mkdirs();
            }

            for (MultipartFile file : files) {
                File dest = new File(path + file.getOriginalFilename());
                file.transferTo(dest);
            }
        } catch (IOException e) {
            throw new WebException(HttpStatus.INTERNAL_SERVER_ERROR, e);
        }

        return result;
    }

    @Override
    public void deleteByTypeAndRefId(String type, Integer refId) {
        repository.deleteByTypeAndRefId(type, refId);
    }

    @Override
    public List<Upload> findByTypeAndRefIdOrderBySortAsc(String type, Integer refId) {
        List<Upload> uploads = repository.findByTypeAndRefIdOrderBySortAsc(type, refId);
        for (Upload upload : uploads) {
            upload.setUrl(buildUrl(upload));
        }

        return uploads;
    }

    private String buildPath(String type, Integer refId) {
        StringBuilder sb = new StringBuilder(basePath);

        sb.append(type).append(File.separator).append(refId).append(File.separator);

        return sb.toString();
    }

    private String buildUrl(Upload upload) {
        StringBuilder sb = new StringBuilder("upload/");

        sb.append(upload.getType()).append("/").append(upload.getRefId()).append("/").append(upload.getFileName());

        return sb.toString();
    }

	@Override
	public void download(Integer id, OutputStream os) {
		Upload one = repository.findOne(id);
		String path = buildPath(one.getType(), one.getRefId()) + "/" + one.getFileName();

		FileInputStream fis = null;
		try {
			fis = new FileInputStream(path);
			StreamUtils.copy(fis, os);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new WebException(HttpStatus.INTERNAL_SERVER_ERROR, e);
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					// ignor
				}
			}
		}
	}
}
